home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 1 / Amiga Tools.iso / wb-tools / toolmanager / source / library / dockobj.c < prev    next >
C/C++ Source or Header  |  1994-06-06  |  44KB  |  1,348 lines

  1. /*
  2.  * dockobj.c  V2.1
  3.  *
  4.  * TMObject, Type: Dock
  5.  *
  6.  * (c) 1990-1993 Stefan Becker
  7.  */
  8.  
  9. #include "ToolManagerLib.h"
  10.  
  11. /* node for one tool */
  12. struct DockTool {
  13.                  struct DockTool    *dt_Next;
  14.                  char               *dt_ExecName;
  15.                  struct TMLink      *dt_ExecLink;
  16.                  struct TMLinkImage *dt_ImageLink;
  17.                  struct TMLink      *dt_SoundLink;
  18.                 };
  19.  
  20. /* extended TMObject structure for TMOBJTYPE_Dock objects */
  21. struct TMObjectDock {
  22.                      struct TMObject  do_Object;
  23.                      ULONG            do_Flags;
  24.                      ULONG            do_Columns;
  25.                      struct TextAttr *do_Font;   /* User supplied font */
  26.                      char            *do_HotKey;
  27.                      ULONG            do_LeftEdge;
  28.                      char            *do_PubScreen;
  29.                      char            *do_Title;
  30.                      struct DockTool *do_Tools;
  31.                      ULONG            do_TopEdge;
  32.                      CxObj           *do_CxObj;
  33.                      struct TMLink    do_Link;
  34.                      UWORD            do_Left;   /* Drawing start position */
  35.                      UWORD            do_Top;
  36.                      UWORD            do_Width;  /* Inner Window Width/Height */
  37.                      UWORD            do_Height;
  38.                      UWORD            do_XSize;  /* Image/Gadget box size */
  39.                      UWORD            do_YSize;
  40.                      struct Window   *do_Window;
  41.                      void            *do_AppWindow;
  42.                      struct Gadget    do_DragGadget;
  43.                      UWORD            do_FillPen;
  44.                      UWORD            do_BackPen;
  45.                      struct TextAttr  do_TextAttr;   /* Font for gadgets */
  46.                      struct TextFont *do_TextFont;   /* Screen font (open) */
  47.                      struct TextFont *do_GadgetFont; /* Gadget font (open) */
  48.                      void            *do_VisualInfo;
  49.                      struct Menu     *do_Menu;
  50.                      struct Gadget   *do_GadToolsGadgets;
  51.                      struct DockTool *do_Selected;
  52.                      UWORD            do_SelectX;
  53.                      UWORD            do_SelectY;
  54.                      ULONG            do_Seconds;
  55.                      ULONG            do_Micros;
  56.                      BOOL             do_DeferClose;
  57.                     };
  58.  
  59. /* do_Flags */
  60. #define DO_Activated (1L<<0)
  61. #define DO_Centered  (1L<<1)
  62. #define DO_FrontMost (1L<<2)
  63. #define DO_Menu      (1L<<3)
  64. #define DO_Pattern   (1L<<4)
  65. #define DO_PopUp     (1L<<5)
  66. #define DO_Text      (1L<<6)
  67. #define DO_Vertical  (1L<<7)
  68. #define DO_Backdrop  (1L<<8)
  69. #define DO_Sticky    (1L<<9)
  70.  
  71. /* Tag to Flag mapping table for PackBoolTags */
  72. static struct TagItem flagmap[]={
  73.                                  TMOP_Activated, DO_Activated,
  74.                                  TMOP_Centered,  DO_Centered,
  75.                                  TMOP_FrontMost, DO_FrontMost,
  76.                                  TMOP_Menu,      DO_Menu,
  77.                                  TMOP_Pattern,   DO_Pattern,
  78.                                  TMOP_PopUp,     DO_PopUp,
  79.                                  TMOP_Text,      DO_Text,
  80.                                  TMOP_Vertical,  DO_Vertical,
  81.                                  TMOP_Backdrop,  DO_Backdrop,
  82.                                  TMOP_Sticky,    DO_Sticky,
  83.                                  TAG_DONE};
  84.  
  85. /* Library bases */
  86. struct Library *DiskfontBase;
  87.  
  88. /* Close a window safely */
  89. static void SafeCloseWindow(struct Window *w)
  90. {
  91.  struct IntuiMessage *msg;
  92.  
  93.  DEBUG_PRINTF("SafeCloseWindow: 0x%08lx\n",w);
  94.  
  95.  /* we forbid here to keep out of race conditions with Intuition */
  96.  Forbid();
  97.  
  98.  /* Remove all messsages for this window */
  99.  msg=GetHead(&w->UserPort->mp_MsgList);
  100.  while (msg)
  101.   /* Does this message point to the window? */
  102.   if (msg->IDCMPWindow==w) {
  103.    struct IntuiMessage *nextmsg=GetSucc(msg);
  104.  
  105.    /* Yes. Remove it from port */
  106.    Remove((struct Node *) msg);
  107.  
  108.    /* Reply it */
  109.    ReplyMsg((struct Message *) msg);
  110.  
  111.    /* Get pointer to next message */
  112.    msg=nextmsg;
  113.   }
  114.    /* No. Get pointer to next message */
  115.   else msg=GetSucc(msg);
  116.  
  117.  /* clear UserPort so Intuition will not free it */
  118.  w->UserPort=NULL;
  119.  
  120.  /* tell Intuition to stop sending more messages */
  121.  ModifyIDCMP(w,0);
  122.  
  123.  /* turn multitasking back on */
  124.  Permit();
  125.  
  126.  DEBUG_PRINTF("Closing window\n");
  127.  
  128.  /* and really close the window */
  129.  CloseWindow(w);
  130.  
  131.  DEBUG_PRINTF("Window closed\n");
  132. }
  133.  
  134. /* Pattern */
  135. static UWORD BackgroundPattern[]={0xaaaa,0x5555};
  136.  
  137. /* Open Dock Window */
  138. static void OpenDockWindow(struct TMObjectDock *tmobj)
  139. {
  140.  struct Screen *pubsc;
  141.  
  142.  /* Open on frontmost public screen? */
  143.  if (tmobj->do_Flags & DO_FrontMost) {
  144.   ULONG lock;
  145.  
  146.   /* Avoid race conditions */
  147.   Forbid();
  148.  
  149.   /* Lock IntuitionBase */
  150.   lock=LockIBase(0);
  151.  
  152.   /* Get active screen */
  153.   pubsc=IntuitionBase->ActiveScreen;
  154.   if (pubsc) {
  155.    ULONG type=pubsc->Flags & SCREENTYPE;
  156.  
  157.    DEBUG_PRINTF("Screen flags: 0x%08lx",pubsc->Flags);
  158.    DEBUG_PRINTF(" Screen type: 0x%08lx\n",type);
  159.  
  160.    /* Found a public screen? */
  161.    if (!((type==WBENCHSCREEN) || (type==PUBLICSCREEN)))
  162.     /* No! */
  163.     pubsc=NULL;
  164.   }
  165.  
  166.   /* Unlock IntuitionBase */
  167.   UnlockIBase(lock);
  168.  
  169.   /* Lock public screen */
  170.   if (pubsc) {
  171.    struct List *pubsclist;
  172.  
  173.    /* Get a pointer to the public screen list */
  174.    if (pubsclist=LockPubScreenList()) {
  175.     struct PubScreenNode *pubscnode=GetHead(pubsclist);
  176.     UBYTE namebuf[MAXPUBSCREENNAME+1];
  177.  
  178.     /* Scan list */
  179.     while (pubscnode) {
  180.      /* Does this node point to our screen? */
  181.      if (pubscnode->psn_Screen==pubsc) {
  182.       /* Yes. Copy screen name */
  183.       strcpy(namebuf,pubscnode->psn_Node.ln_Name);
  184.       break;
  185.      }
  186.  
  187.      /* get a pointer to next node */
  188.      pubscnode=GetSucc(pubscnode);
  189.     }
  190.  
  191.     /* Release public screen list */
  192.     UnlockPubScreenList();
  193.  
  194.     /* Lock screen */
  195.     if (pubscnode)
  196.      pubsc=LockPubScreen(namebuf);
  197.     else
  198.      pubsc=NULL;
  199.    }
  200.    else pubsc=NULL; /* No public screens??? */
  201.   }
  202.  
  203.   /* OK, we have a screen now */
  204.   Permit();
  205.  } else
  206.   /* Lock public screen */
  207.   pubsc=LockPubScreen(tmobj->do_PubScreen);
  208.  
  209.  DEBUG_PRINTF("PubScreen: 0x%08lx\n",pubsc);
  210.  
  211.  /* Got a locked public screen? */
  212.  if (pubsc) {
  213.   struct DrawInfo *dri;
  214.  
  215.   /* Get screen draw info */
  216.   if (dri=GetScreenDrawInfo(pubsc)) {
  217.    void *vi;
  218.  
  219.    /* Get screen visual info */
  220.    if (vi=GetVisualInfo(pubsc,TAG_DONE)) {
  221.     struct TextFont *tf;
  222.  
  223.     /* Open screen font */
  224.     if (tf=OpenFont(pubsc->Font)) {
  225.      struct Window *w;
  226.      struct DockTool *dt=tmobj->do_Tools;
  227.      struct TextFont *gadfont=NULL;
  228.      UWORD wx=0,wy=0;
  229.      BOOL borderless=tmobj->do_Title==NULL;
  230.      BOOL text=(tmobj->do_Flags & DO_Text)!=0;
  231.  
  232.      /* Got ANY tools??? */
  233.      if (dt) {
  234.       /* Calculate box sizes */
  235.       ULONG maxx=0,maxy=0,count=0;
  236.       ULONG fheight;
  237.       struct RastPort tmprp;
  238.  
  239.       /* Init RastPort for text writing */
  240.       InitRastPort(&tmprp);
  241.  
  242.       /* Set default font */
  243.       SetFont(&tmprp,tf);
  244.       fheight=tf->tf_YSize+INTERHEIGHT+1;
  245.  
  246.       /* User specified font? */
  247.       if (tmobj->do_Font &&
  248.           (DiskfontBase=OpenLibrary("diskfont.library",36))) {
  249.        /* OK, load font now */
  250.        if (gadfont=OpenDiskFont(tmobj->do_Font)) {
  251.         /* Set font */
  252.         SetFont(&tmprp,gadfont);
  253.         fheight=gadfont->tf_YSize+INTERHEIGHT+1;
  254.        }
  255.  
  256.        /* Close library again */
  257.        CloseLibrary(DiskfontBase);
  258.       }
  259.  
  260.       DEBUG_PRINTF("TextAttr: 0x%08lx",tmobj->do_Font);
  261.       DEBUG_PRINTF(" Font: 0x%08lx\n",gadfont);
  262.  
  263.       /* Scan tool list */
  264.       while (dt) {
  265.        ULONG valx=0,valy=0;
  266.  
  267.        if (text) {
  268.         /* Gadgets */
  269.         char *s=dt->dt_ExecName;
  270.  
  271.         /* Link and name valid? */
  272.         if (dt->dt_ExecLink && s) {
  273.          valx=TextLength(&tmprp,s,strlen(s))+2*INTERWIDTH+2;
  274.          valy=fheight;
  275.         }
  276.        } else {
  277.         /* Images */
  278.         struct TMLinkImage *tmli=dt->dt_ImageLink;
  279.  
  280.         /* Link to image valid? */
  281.         if (tmli) {
  282.          /* max(width) */
  283.          valx=tmli->tmli_Width;
  284.          valy=tmli->tmli_Height-1;
  285.         }
  286.        }
  287.  
  288.        /* Check maxima */
  289.        if (valx>maxx) maxx=valx;
  290.        if (valy>maxy) maxy=valy;
  291.  
  292.        /* Increment counter & Get pointer to next tool */
  293.        count++;
  294.        dt=dt->dt_Next;
  295.       }
  296.  
  297.       /* Calculate window sizes */
  298.       tmobj->do_Width=tmobj->do_Columns*maxx;
  299.       tmobj->do_Height=((count+tmobj->do_Columns-1)/tmobj->do_Columns)*maxy;
  300.       tmobj->do_XSize=maxx;
  301.       tmobj->do_YSize=maxy;
  302.      }
  303.  
  304.      /* Got valid window sizes? */
  305.      if (((LONG) tmobj->do_XSize>1) && ((LONG) tmobj->do_YSize>1) &&
  306.          (tmobj->do_Columns>0) && (tmobj->do_Columns<=100)) {
  307.       BOOL menu=(tmobj->do_Flags & DO_Menu)!=0;
  308.  
  309.       /* Correct window sizes */
  310.       if (borderless) {
  311.        /* Borderless window */
  312.        struct Gadget *g=&tmobj->do_DragGadget;
  313.  
  314.        /* Gadget window */
  315.        if (text) {
  316.         tmobj->do_Width--;
  317.         tmobj->do_Height--;
  318.        }
  319.  
  320.        /* Calculate drag gadget dimensions */
  321.        if (tmobj->do_Flags & DO_Vertical) {
  322.         /* Vertical drag gadget */
  323.         struct RastPort tmprp;
  324.         UWORD gwidth;
  325.  
  326.         /* Init RastPort for text writing */
  327.         InitRastPort(&tmprp);
  328.         SetFont(&tmprp,tf);
  329.         gwidth=TextLength(&tmprp,"A",1);
  330.  
  331.         tmobj->do_Left=gwidth;
  332.         tmobj->do_Top=0;
  333.         tmobj->do_Width+=gwidth;
  334.         g->Width=gwidth;
  335.         g->Height=tmobj->do_Height;
  336.        } else {
  337.         /* Horizontal drag gadget */
  338.         UWORD gheight=(tf->tf_YSize+8)/2;
  339.  
  340.         tmobj->do_Left=0;
  341.         tmobj->do_Top=gheight;
  342.         tmobj->do_Height+=gheight;
  343.         g->Width=tmobj->do_Width;
  344.         g->Height=gheight;
  345.        }
  346.  
  347.        /* Init drag gadget structure */
  348.        g->Flags=GFLG_GADGHNONE;
  349.        g->Activation=GACT_IMMEDIATE;
  350.        g->GadgetType=GTYP_SYSGADGET|GTYP_WDRAGGING;
  351.  
  352.        /* Get pens */
  353.        tmobj->do_FillPen=dri->dri_Pens[FILLPEN];
  354.        tmobj->do_BackPen=dri->dri_Pens[BACKGROUNDPEN];
  355.       } else {
  356.        /* Normal window */
  357.        tmobj->do_Left=pubsc->WBorLeft+1;
  358.        tmobj->do_Top=pubsc->WBorTop+tf->tf_YSize+2;
  359.        if (text) {
  360.         tmobj->do_Width++;
  361.         tmobj->do_Height++;
  362.        } else {
  363.         tmobj->do_Width+=2;
  364.         tmobj->do_Height+=2;
  365.        }
  366.       }
  367.  
  368.       /* Centered window? */
  369.       if (tmobj->do_Flags & DO_Centered) {
  370.        /* Centered */
  371.        /* Borderless window: X = MouseX - (width-left)/2 - left */
  372.        /* Normal window    : X = MouseX -        width/2 - left */
  373.        wx=tmobj->do_Width;
  374.        wy=tmobj->do_Height;
  375.  
  376.        /* Borderless window? */
  377.        if (borderless) {
  378.         wx-=tmobj->do_Left;
  379.         wy-=tmobj->do_Top;
  380.        }
  381.  
  382.        wx=pubsc->MouseX-wx/2-tmobj->do_Left;
  383.        wy=pubsc->MouseY-wy/2-tmobj->do_Top;
  384.       } else {
  385.        /* Not centered */
  386.        wx=tmobj->do_LeftEdge;
  387.        wy=tmobj->do_TopEdge;
  388.       }
  389.  
  390.       /* Dock with menu? */
  391.       if (menu &&
  392.           (tmobj->do_Menu=CreateMenus(DockMenu,GTMN_FullMenu, TRUE,
  393.                                                TAG_DONE)) &&
  394.           !LayoutMenus(tmobj->do_Menu,vi,GTMN_NewLookMenus, TRUE,
  395.                                          TAG_DONE)) {
  396.        FreeMenus(tmobj->do_Menu);
  397.        tmobj->do_Menu=NULL;
  398.       }
  399.  
  400.       DEBUG_PRINTF("Boxes: X %ld",tmobj->do_XSize);
  401.       DEBUG_PRINTF(" Y %ld",tmobj->do_YSize);
  402.       DEBUG_PRINTF(" Window: Width %ld",tmobj->do_Width);
  403.       DEBUG_PRINTF(" Height %ld\n",tmobj->do_Height);
  404.       DEBUG_PRINTF("menu %ld",menu);
  405.       DEBUG_PRINTF(" Menu 0x%08lx\n",tmobj->do_Menu);
  406.  
  407.       /* Open window */
  408.       if ((!menu || tmobj->do_Menu) &&
  409.           (w=OpenWindowTags(NULL,WA_Left,         wx,
  410.                                  WA_Top,          wy,
  411.                                  WA_InnerWidth,   tmobj->do_Width,
  412.                                  WA_InnerHeight,  tmobj->do_Height,
  413.                                  WA_Title,        tmobj->do_Title,
  414.                                  WA_DragBar,      !borderless,
  415.                                  WA_CloseGadget,  !borderless,
  416.                                  WA_DepthGadget,  !borderless,
  417.                                  WA_Borderless,   borderless,
  418.                                  WA_PubScreen,    pubsc,
  419.                                  WA_RMBTrap,      !menu,
  420.                                  WA_AutoAdjust,   TRUE,
  421.                                  WA_IDCMP,        0,
  422.                                  WA_NewLookMenus, TRUE,
  423.                                  TAG_DONE))) {
  424.        /* Backdrop window? */
  425.        if (tmobj->do_Flags & DO_Backdrop) WindowToBack(w);
  426.  
  427.        /* Set window pointers */
  428.        w->UserPort=IDCMPPort;
  429.        w->UserData=(APTR) tmobj;
  430.  
  431.        DEBUG_PRINTF("Window: 0x%08lx\n",w);
  432.  
  433.        /* Set IDCMP flags */
  434.        if (ModifyIDCMP(w,IDCMP_ACTIVEWINDOW|IDCMP_INACTIVEWINDOW|IDCMP_GADGETUP|
  435.                          IDCMP_MOUSEBUTTONS|IDCMP_CLOSEWINDOW|IDCMP_MENUPICK|
  436.                          IDCMP_REFRESHWINDOW)) {
  437.         struct Gadget *g;
  438.         BOOL wbscreen=(pubsc->Flags & SCREENTYPE)==WBENCHSCREEN;
  439.  
  440.         /* Try to add the window as application window */
  441.         tmobj->do_AppWindow=NULL;
  442.         if (wbscreen && GetWorkbench() &&
  443.             !(tmobj->do_AppWindow=AddAppWindowA((ULONG) &tmobj->do_Link,
  444.                                                 NULL,w,AppMsgPort,NULL)))
  445.          /* AddAppWindow() failed (Workbench not running?) */
  446.          FreeWorkbench();
  447.  
  448.         /* Draw drag gadget */
  449.         if (borderless) {
  450.          struct RastPort *rp=w->RPort;
  451.          UWORD width=tmobj->do_DragGadget.Width-1;
  452.          UWORD height=tmobj->do_DragGadget.Height-1;
  453.  
  454.          /* Draw lighted side */
  455.          SetAPen(rp,dri->dri_Pens[SHINEPEN]);
  456.          Move(rp,0,height);
  457.          Draw(rp,0,0);
  458.          Draw(rp,width,0);
  459.  
  460.          /* Draw shadowed side */
  461.          SetAPen(rp,dri->dri_Pens[SHADOWPEN]);
  462.          Move(rp,width,1);
  463.          Draw(rp,width,height);
  464.          Draw(rp,0,height);
  465.  
  466.          AddGadget(w,&tmobj->do_DragGadget,(UWORD) -1);
  467.          RefreshGList(&tmobj->do_DragGadget,w,NULL,1);
  468.         }
  469.  
  470.         /* Draw initial window state */
  471.         {
  472.          struct RastPort *rp=w->RPort;
  473.          ULONG col=0,lin=0;
  474.          UWORD x=tmobj->do_Left;
  475.          UWORD y=tmobj->do_Top;
  476.          UWORD dw=tmobj->do_XSize;
  477.          UWORD dh=tmobj->do_YSize;
  478.          BOOL pattern=((tmobj->do_Flags & DO_Pattern)!=0 && !text);
  479.          struct NewGadget ng;
  480.  
  481.          /* Set pattern */
  482.          if (pattern) {
  483.           SetAPen(rp,dri->dri_Pens[SHADOWPEN]);
  484.           SetDrMd(rp,JAM2);
  485.           SetAfPt(rp,BackgroundPattern,1);
  486.          }
  487.  
  488.          /* Set pointer to begin of tool list */
  489.          dt=tmobj->do_Tools;
  490.  
  491.          /* Init TextAttr & NewGadget struct, create GadTools context */
  492.          if (text) {
  493.           /* Font set? */
  494.           if (tmobj->do_Font)
  495.            tmobj->do_TextAttr=*(tmobj->do_Font);
  496.           else {
  497.            /* No. Set screen font */
  498.            tmobj->do_TextAttr.ta_Name=tf->tf_Message.mn_Node.ln_Name;
  499.            tmobj->do_TextAttr.ta_YSize=tf->tf_YSize;
  500.            tmobj->do_TextAttr.ta_Style=tf->tf_Style;
  501.            tmobj->do_TextAttr.ta_Flags=tf->tf_Flags;
  502.           }
  503.  
  504.           DEBUG_PRINTF("Font '%s'",tmobj->do_TextAttr.ta_Name);
  505.           DEBUG_PRINTF(" Size %ld\n",tmobj->do_TextAttr.ta_YSize);
  506.  
  507.           ng.ng_Width=dw-1;
  508.           ng.ng_Height=dh-1;
  509.           ng.ng_TextAttr=&tmobj->do_TextAttr;
  510.           ng.ng_Flags=PLACETEXT_IN;
  511.           ng.ng_VisualInfo=vi;
  512.           ng.ng_UserData=0;
  513.           tmobj->do_GadToolsGadgets=NULL;
  514.           if (!(g=CreateContext(&tmobj->do_GadToolsGadgets)))
  515.            dt=NULL; /* Error!!! */
  516.          }
  517.  
  518.          /* Scan tool list */
  519.          while (dt) {
  520.           if (text) {
  521.            /* Gadgets. Link valid? */
  522.            if (dt->dt_ExecLink) {
  523.             /* Init NewGadget values */
  524.             ng.ng_LeftEdge=x;
  525.             ng.ng_TopEdge=y;
  526.             ng.ng_GadgetText=dt->dt_ExecName;
  527.             ng.ng_UserData=dt;
  528.  
  529.             /* Create button gadget */
  530.             if (!(g=CreateGadget(BUTTON_KIND,g,&ng,TAG_DONE)))
  531.              dt=NULL; /* Error!!!! */
  532.            }
  533.           } else {
  534.            /* Images */
  535.            struct TMLinkImage *tmli=dt->dt_ImageLink;
  536.  
  537.            /* Draw pattern? */
  538.            if (pattern) {
  539.             /* Set Pattern color */
  540.             SetBPen(rp,(col+lin)&1 ? dri->dri_Pens[BACKGROUNDPEN] :
  541.                                      dri->dri_Pens[FILLPEN]);
  542.  
  543.             /* Draw pattern */
  544.             RectFill(rp,x,y,x+dw-1,y+dh-1);
  545.            }
  546.  
  547.            /* Link valid? */
  548.            if (tmli) {
  549.             /* Yes. Set Parameters */
  550.             tmli->tmli_LeftEdge=x+(dw - tmli->tmli_Width)/2;
  551.             tmli->tmli_TopEdge=y+(dh + 1 - tmli->tmli_Height)/2;
  552.             tmli->tmli_RastPort=w->RPort;
  553.  
  554.             /* Draw deactivated state */
  555.             CallActivateTMObject((struct TMLink *) tmli,(void *) IOC_DEACTIVE);
  556.            }
  557.           }
  558.  
  559.           /* Next column */
  560.           col++;
  561.  
  562.           /* Increment x,y. Last Column? */
  563.           if (col==tmobj->do_Columns) {
  564.            /* Yes */
  565.            y+=dh;
  566.            x=tmobj->do_Left;
  567.            col=0;
  568.            lin++;
  569.           } else
  570.            /* No */
  571.            x+=dw;
  572.  
  573.           /* Get pointer to next node */
  574.           if (dt) dt=dt->dt_Next;
  575.          }
  576.  
  577.          /* Reset Areafill pattern */
  578.          if (pattern) SetAfPt(rp,NULL,0);
  579.         }
  580.  
  581.         /* All OK. */
  582.         if (!text || g) {
  583.          /* Add GadTools gadgets */
  584.          if (text) {
  585.           AddGList(w,tmobj->do_GadToolsGadgets,(UWORD) -1,(UWORD) -1,NULL);
  586.           RefreshGList(tmobj->do_GadToolsGadgets,w,NULL,(UWORD) -1);
  587.           GT_RefreshWindow(w,NULL);
  588.          }
  589.  
  590.          /* Add menu */
  591.          if (menu) SetMenuStrip(w,tmobj->do_Menu);
  592.  
  593.          /* Free resources */
  594.          FreeScreenDrawInfo(pubsc,dri);
  595.          UnlockPubScreen(NULL,pubsc);
  596.  
  597.          /* Save pointers */
  598.          tmobj->do_VisualInfo=vi;
  599.          tmobj->do_TextFont=tf;
  600.          tmobj->do_GadgetFont=gadfont;
  601.          tmobj->do_Window=w;
  602.          tmobj->do_DeferClose=FALSE;
  603.          return;
  604.          /* NOT REACHED */
  605.         }
  606.  
  607.         /* Remove drag Gadget */
  608.         if (borderless) RemoveGadget(w,&tmobj->do_DragGadget);
  609.  
  610.         /* Free GadTools gadgets */
  611.         if (text) {
  612.          FreeGadgets(tmobj->do_GadToolsGadgets);
  613.          tmobj->do_GadToolsGadgets=NULL;
  614.         }
  615.  
  616.         /* Remove AppWindow, close Workbench */
  617.         if (tmobj->do_AppWindow) {
  618.          SafeRemoveAppWindow(tmobj->do_AppWindow,&tmobj->do_Link);
  619.          FreeWorkbench();
  620.         }
  621.        }
  622.        SafeCloseWindow(w);
  623.       }
  624.       if (tmobj->do_Menu) {
  625.        FreeMenus(tmobj->do_Menu);
  626.        tmobj->do_Menu=NULL;
  627.       }
  628.      }
  629.      if (gadfont) CloseFont(gadfont);
  630.      CloseFont(tf);
  631.     }
  632.     FreeVisualInfo(vi);
  633.    }
  634.    FreeScreenDrawInfo(pubsc,dri);
  635.   }
  636.   UnlockPubScreen(NULL,pubsc);
  637.  }
  638.  /* Dock couldn't be opened! */
  639.  DisplayBeep(NULL);
  640. }
  641.  
  642. /* Close Dock window */
  643. static void CloseDockWindow(struct TMObjectDock *tmobj)
  644. {
  645.  struct DockTool *dt=tmobj->do_Tools;
  646.  struct Window *w=tmobj->do_Window;
  647.  
  648.  DEBUG_PRINTF("CloseDockWindow: 0x%08lx\n",tmobj);
  649.  
  650.  /* Deactivate all Image objects */
  651.  while (dt) {
  652.   /* Image object active? */
  653.   if (dt->dt_ImageLink && dt->dt_ImageLink->tmli_Link.tml_Active)
  654.    /* Yes. Deactivate it first */
  655.    CallActivateTMObject((struct TMLink *) dt->dt_ImageLink,
  656.                         (void *) IOC_DEACTIVE);
  657.  
  658.   /* Get pointer to next node */
  659.   dt=dt->dt_Next;
  660.  }
  661.  
  662.  /* Remove menu */
  663.  if (tmobj->do_Menu) {
  664.   ClearMenuStrip(w);
  665.   FreeMenus(tmobj->do_Menu);
  666.   tmobj->do_Menu=NULL;
  667.  }
  668.  
  669.  /* Remove drag gadget */
  670.  if (!tmobj->do_Title) RemoveGadget(w,&tmobj->do_DragGadget);
  671.  
  672.  /* Remove gadtools gadgets */
  673.  if (tmobj->do_GadToolsGadgets) {
  674.   RemoveGList(w,tmobj->do_GadToolsGadgets,(UWORD) -1);
  675.   FreeGadgets(tmobj->do_GadToolsGadgets);
  676.   tmobj->do_GadToolsGadgets=NULL;
  677.  }
  678.  
  679.  /* Remove AppWindow, free Workbench */
  680.  if (tmobj->do_AppWindow) {
  681.   SafeRemoveAppWindow(tmobj->do_AppWindow,&tmobj->do_Link);
  682.   FreeWorkbench();
  683.  }
  684.  
  685.  /* Sticky window? */
  686.  if (!(tmobj->do_Flags & DO_Sticky)) {
  687.   /* No, remember last window position */
  688.   tmobj->do_LeftEdge=w->LeftEdge;
  689.   tmobj->do_TopEdge=w->TopEdge;
  690.  }
  691.  
  692.  /* Close Window */
  693.  SafeCloseWindow(w);
  694.  tmobj->do_Window=NULL;
  695.  
  696.  /* Free resources */
  697.  if (tmobj->do_GadgetFont) CloseFont(tmobj->do_GadgetFont);
  698.  CloseFont(tmobj->do_TextFont);
  699.  FreeVisualInfo(tmobj->do_VisualInfo);
  700. }
  701.  
  702. /* Free tools list */
  703. static void FreeTools(struct TMObjectDock *tmobj)
  704. {
  705.  struct DockTool *dt,*nextdt=tmobj->do_Tools;
  706.  
  707.  /* Scan list */
  708.  while (dt=nextdt) {
  709.   /* Get pointer to next node */
  710.   nextdt=dt->dt_Next;
  711.  
  712.   /* Remove links */
  713.   if (dt->dt_ExecLink) RemLinkTMObject(dt->dt_ExecLink);
  714.   if (dt->dt_ImageLink) RemLinkTMObject((struct TMLink *) dt->dt_ImageLink);
  715.   if (dt->dt_SoundLink) RemLinkTMObject(dt->dt_SoundLink);
  716.  
  717.   /* Free Node */
  718.   FreeMem(dt,sizeof(struct DockTool));
  719.  }
  720. }
  721.  
  722. /* Create a Dock object */
  723. struct TMObject *CreateTMObjectDock(struct TMHandle *handle, char *name,
  724.                                     struct TagItem *tags)
  725. {
  726.  struct TMObjectDock *tmobj;
  727.  
  728.  /* allocate memory for object */
  729.  if (tmobj=(struct TMObjectDock *)
  730.             AllocateTMObject(sizeof(struct TMObjectDock))) {
  731.   struct TagItem *ti,*tstate;
  732.   struct DockTool *dt=NULL;
  733.  
  734.   /* Set defaults */
  735.   tmobj->do_Columns=1;
  736.  
  737.   /* Scan tag list */
  738.   tstate=tags;
  739.   while (ti=NextTagItem(&tstate)) {
  740.  
  741.    DEBUG_PRINTF("Got Tag (0x%08lx)\n",ti->ti_Tag);
  742.  
  743.    switch (ti->ti_Tag) {
  744.     case TMOP_Columns:   if (ti->ti_Data) tmobj->do_Columns=ti->ti_Data;
  745.                          break;
  746.     case TMOP_Font:      {
  747.                           struct TextAttr *ta=(struct TextAttr *) ti->ti_Data;
  748.  
  749.                           if (ta && ta->ta_Name) tmobj->do_Font=ta;
  750.                          }
  751.                          break;
  752.     case TMOP_HotKey:    tmobj->do_HotKey=(char *) ti->ti_Data;
  753.                          break;
  754.     case TMOP_LeftEdge:  tmobj->do_LeftEdge=ti->ti_Data;
  755.                          break;
  756.     case TMOP_PubScreen: tmobj->do_PubScreen=(char *) ti->ti_Data;
  757.                          break;
  758.     case TMOP_Title:     tmobj->do_Title=(char *) ti->ti_Data;
  759.                          break;
  760.     case TMOP_Tool:      if (ti->ti_Data) {
  761.                           struct DockTool *newdt;
  762.  
  763.                           /* Alloc DockTool structure */
  764.                           if (newdt=AllocMem(sizeof(struct DockTool),
  765.                                              MEMF_CLEAR)) {
  766.                            char **names=(char **) ti->ti_Data;
  767.  
  768.                            /* Add link to Exec object */
  769.                            if (names[0] &&
  770.                                (newdt->dt_ExecLink=AddLinkTMObject(handle,
  771.                                                                   names[0],
  772.                                                                 TMOBJTYPE_EXEC,
  773.                                                             (struct TMObject *)
  774.                                                                   tmobj)))
  775.                             /* Get name of exec object. We use names[0]
  776.                                instead of object name, because the link could
  777.                                be deleted while window is still active. */
  778.                             newdt->dt_ExecName=names[0];
  779.  
  780.                            /* Add link to Image object */
  781.                            if (names[1])
  782.                             newdt->dt_ImageLink=(struct TMLinkImage *)
  783.                                     AddLinkTMObject(handle,names[1],
  784.                                                     TMOBJTYPE_IMAGE,
  785.                                                     (struct TMObject *) tmobj);
  786.  
  787.                            /* Add link to Sound object */
  788.                            if (names[2])
  789.                             newdt->dt_SoundLink=AddLinkTMObject(handle,names[2],
  790.                                                                 TMOBJTYPE_SOUND,
  791.                                                             (struct TMObject *)
  792.                                                                 tmobj);
  793.  
  794.                            /* Add node to list. Head of list? */
  795.                            if (dt) {
  796.                             /* No. Add to tail */
  797.                             dt->dt_Next=newdt;
  798.                             dt=newdt;
  799.                            } else {
  800.                             /* Yes. Init list anchor */
  801.                             tmobj->do_Tools=newdt;
  802.                             dt=newdt;
  803.                            }
  804.                           }
  805.                          }
  806.                          break;
  807.     case TMOP_TopEdge:   tmobj->do_TopEdge=ti->ti_Data;
  808.                          break;
  809.    }
  810.   }
  811.  
  812.   {
  813.    BOOL hotkey=tmobj->do_HotKey!=NULL;
  814.  
  815.    /* No HotKey or cannot create CxObject from HotKey description? */
  816.    if (hotkey && (tmobj->do_CxObj=HotKey(tmobj->do_HotKey,BrokerPort,
  817.                                          (ULONG) &tmobj->do_Link))) {
  818.  
  819.     DEBUG_PRINTF("Created CxObj (0x%08lx)\n",tmobj->do_CxObj);
  820.  
  821.     /* Attach object to broker */
  822.     AttachCxObj(Broker,tmobj->do_CxObj);
  823.    }
  824.  
  825.    /* No HotKey or Commodities error? */
  826.    if (!hotkey || (tmobj->do_CxObj && !CxObjError(Broker))) {
  827.     /* Set flags */
  828.     tmobj->do_Flags=PackBoolTags(DO_Activated,tags,flagmap);
  829.  
  830.     /* Initialize rest of structure */
  831.     tmobj->do_Link.tml_Linked=(struct TMObject *) tmobj;
  832.  
  833.     /* Active flag set? */
  834.     if (tmobj->do_Flags & DO_Activated)
  835.      /* Yes. Open dock window */
  836.      OpenDockWindow(tmobj);
  837.  
  838.     /* All OK */
  839.     return(tmobj);
  840.    }
  841.  
  842.    /* Free resources */
  843.    if (tmobj->do_CxObj) SafeDeleteCxObjAll(tmobj->do_CxObj,&tmobj->do_Link);
  844.   }
  845.   FreeTools(tmobj);
  846.  }
  847.  
  848.  /* call failed */
  849.  return(NULL);
  850. }
  851.  
  852. /* Delete a Dock object */
  853. BOOL DeleteTMObjectDock(struct TMObjectDock *tmobj)
  854. {
  855.  DEBUG_PRINTF("Delete/Dock (0x%08lx)\n",tmobj);
  856.  
  857.  /* Remove links */
  858.  DeleteAllLinksTMObject((struct TMObject *) tmobj);
  859.  
  860.  /* Free resources */
  861.  if (tmobj->do_CxObj) SafeDeleteCxObjAll(tmobj->do_CxObj,&tmobj->do_Link);
  862.  
  863.  /* Close window and free its resources */
  864.  if (tmobj->do_Window) CloseDockWindow(tmobj);
  865.  
  866.  /* Free tool nodes */
  867.  FreeTools(tmobj);
  868.  
  869.  /* Remove object from list */
  870.  Remove((struct Node *) tmobj);
  871.  
  872.  /* Free object */
  873.  FreeMem(tmobj,sizeof(struct TMObjectDock));
  874.  
  875.  /* All OK. */
  876.  return(TRUE);
  877. }
  878.  
  879. /* Change a Dock object */
  880. struct TMObject *ChangeTMObjectDock(struct TMHandle *handle,
  881.                                     struct TMObjectDock *tmobj,
  882.                                     struct TagItem *tags)
  883. {
  884.  struct TagItem *ti,*tstate;
  885.  struct DockTool *dt;
  886.  
  887.  /* Search last dock tool */
  888.  dt=tmobj->do_Tools;
  889.  if (dt)
  890.   while (dt->dt_Next) dt=dt->dt_Next;
  891.  
  892.  /* Close dock */
  893.  if (tmobj->do_Window) CloseDockWindow(tmobj);
  894.  
  895.  /* Scan tag list */
  896.  tstate=tags;
  897.  while (ti=NextTagItem(&tstate)) {
  898.  
  899.   DEBUG_PRINTF("Got Tag (0x%08lx)\n",ti->ti_Tag);
  900.  
  901.   switch (ti->ti_Tag) {
  902.    case TMOP_Columns:   if (ti->ti_Data) tmobj->do_Columns=ti->ti_Data;
  903.                         break;
  904.    case TMOP_Font:      {
  905.                          struct TextAttr *ta=(struct TextAttr *) ti->ti_Data;
  906.  
  907.                          if (ta && ta->ta_Name) tmobj->do_Font=ta;
  908.                         }
  909.                         break;
  910.    case TMOP_HotKey:    if (tmobj->do_CxObj) {
  911.                          SafeDeleteCxObjAll(tmobj->do_CxObj,&tmobj->do_Link);
  912.                          tmobj->do_CxObj=NULL;
  913.                         }
  914.  
  915.                         tmobj->do_HotKey=(char *) ti->ti_Data;
  916.                         break;
  917.    case TMOP_LeftEdge:  tmobj->do_LeftEdge=ti->ti_Data;
  918.                         break;
  919.    case TMOP_PubScreen: tmobj->do_PubScreen=(char *) ti->ti_Data;
  920.                         break;
  921.    case TMOP_Title:     tmobj->do_Title=(char *) ti->ti_Data;
  922.                         break;
  923.    case TMOP_Tool:      if (ti->ti_Data) {
  924.                          struct DockTool *newdt;
  925.  
  926.                          /* Alloc DockTool structure */
  927.                          if (newdt=AllocMem(sizeof(struct DockTool),
  928.                                             MEMF_CLEAR)) {
  929.                           char **names=(char **) ti->ti_Data;
  930.  
  931.                           /* Add link to Exec object */
  932.                           if (names[0] &&
  933.                               (newdt->dt_ExecLink=AddLinkTMObject(handle,
  934.                                                                   names[0],
  935.                                                                 TMOBJTYPE_EXEC,
  936.                                                             (struct TMObject *)
  937.                                                                   tmobj)))
  938.                            /* Get name of exec object. We use names[0]
  939.                               instead of object name, because the link could
  940.                               be deleted while window is still active. */
  941.                            newdt->dt_ExecName=names[0];
  942.  
  943.                           /* Add link to Image object */
  944.                           if (names[1])
  945.                            newdt->dt_ImageLink=(struct TMLinkImage *)
  946.                                     AddLinkTMObject(handle,names[1],
  947.                                                     TMOBJTYPE_IMAGE,
  948.                                                     (struct TMObject *) tmobj);
  949.  
  950.                           /* Add link to Sound object */
  951.                           if (names[2])
  952.                            newdt->dt_SoundLink=AddLinkTMObject(handle,names[2],
  953.                                                                TMOBJTYPE_SOUND,
  954.                                                            (struct TMObject *)
  955.                                                                tmobj);
  956.  
  957.                           /* Add node to list. Head of list? */
  958.                           if (dt) {
  959.                            /* No. Add to tail */
  960.                            dt->dt_Next=newdt;
  961.                            dt=newdt;
  962.                           } else {
  963.                            /* Yes. Init list anchor */
  964.                            tmobj->do_Tools=newdt;
  965.                            dt=newdt;
  966.                           }
  967.                          }
  968.                         }
  969.                         break;
  970.    case TMOP_TopEdge:   tmobj->do_TopEdge=ti->ti_Data;
  971.                         break;
  972.   }
  973.  }
  974.  
  975.  /* Set new flags */
  976.  tmobj->do_Flags=PackBoolTags(tmobj->do_Flags,tags,flagmap);
  977.  
  978.  /* HotKey set? Create Commodities object from HotKey description */
  979.  if (tmobj->do_HotKey && !tmobj->do_CxObj &&
  980.      (tmobj->do_CxObj=HotKey(tmobj->do_HotKey,BrokerPort,
  981.                              (ULONG) &tmobj->do_Link))) {
  982.  
  983.   DEBUG_PRINTF("Created CxObj (0x%08lx)\n",tmobj->do_CxObj);
  984.  
  985.   /* Attach object to broker */
  986.   AttachCxObj(Broker,tmobj->do_CxObj);
  987.  
  988.   /* Commodities error? */
  989.   if (CxObjError(Broker)) {
  990.    SafeDeleteCxObjAll(tmobj->do_CxObj,&tmobj->do_Link);
  991.    tmobj->do_CxObj=NULL;
  992.   }
  993.  }
  994.  
  995.  /* Active flag set? */
  996.  if (tmobj->do_Flags & DO_Activated)
  997.   /* Yes. Open dock window */
  998.   OpenDockWindow(tmobj);
  999.  
  1000.  /* All OK. */
  1001.  return(TRUE);
  1002. }
  1003.  
  1004. /* Allocate & Initialize a TMLink structure */
  1005. struct TMLink *AllocLinkTMObjectDock(struct TMObjectDock *tmobj)
  1006. {
  1007.  struct TMLink *tml;
  1008.  
  1009.  /* Allocate memory for link structure */
  1010.  if (tml=AllocMem(sizeof(struct TMLink),MEMF_CLEAR|MEMF_PUBLIC))
  1011.   /* Initialize link structure */
  1012.   tml->tml_Size=sizeof(struct TMLink);
  1013.  
  1014.  return(tml);
  1015. }
  1016.  
  1017. /* Update link structures */
  1018. void DeleteLinkTMObjectDock(struct TMLink *tml)
  1019. {
  1020.  struct TMObjectDock *tmobj=(struct TMObjectDock *) tml->tml_LinkedTo;
  1021.  struct DockTool *dt=tmobj->do_Tools;
  1022.  
  1023.  /* Scan tool list */
  1024.  while (dt) {
  1025.   /* Link to Exec object? */
  1026.   if (tml==dt->dt_ExecLink) {
  1027.    dt->dt_ExecLink=NULL;
  1028.    dt->dt_ExecName=NULL;
  1029.    break;
  1030.   }
  1031.   /* Link to Image object? */
  1032.   else if (tml==(struct TMLink *) dt->dt_ImageLink) {
  1033.    /* Image object active? */
  1034.    if (tml->tml_Active)
  1035.     /* Yes. Deactivate it */
  1036.     CallActivateTMObject((struct TMLink *) tml,(void *) IOC_DEACTIVE);
  1037.  
  1038.    dt->dt_ImageLink=NULL;
  1039.    break;
  1040.   }
  1041.   /* Link to Sound object? */
  1042.   else if (tml==dt->dt_SoundLink) {
  1043.    dt->dt_SoundLink=NULL;
  1044.    break;
  1045.   }
  1046.  
  1047.   /* Get pointer to next tool */
  1048.   dt=dt->dt_Next;
  1049.  }
  1050. }
  1051.  
  1052. /* Find dock tool that corresponds to X,Y position */
  1053. static struct DockTool *FindDockTool(struct TMObjectDock *tmobj, ULONG x,
  1054.                                      ULONG y)
  1055. {
  1056.  struct DockTool *dt;
  1057.  UWORD dx=tmobj->do_Left;
  1058.  UWORD dy=tmobj->do_Top;
  1059.  UWORD w,h;
  1060.  ULONG col,cols;
  1061.  
  1062.  /* Out of bounds? */
  1063.  if ((x<dx) || (y<dy)) return(NULL); /* Yes! */
  1064.  
  1065.  /* Init variables */
  1066.  dt=tmobj->do_Tools;
  1067.  w=tmobj->do_XSize;
  1068.  h=tmobj->do_YSize;
  1069.  cols=tmobj->do_Columns;
  1070.  col=0;
  1071.  
  1072.  /* Scan dock tool list */
  1073.  while (dt)
  1074.   if ((x>=dx) && (y>=dy) && (x<dx+w) && (y<dy+h)) {
  1075.    /* Tool found */
  1076.    tmobj->do_Selected=dt;
  1077.    tmobj->do_SelectX=dx;
  1078.    tmobj->do_SelectY=dy;
  1079.    return(dt);
  1080.   } else {
  1081.    /* Increment column counter */
  1082.    col++;
  1083.  
  1084.    /* Last column? */
  1085.    if (col==cols) {
  1086.     /* Yes */
  1087.     dx=tmobj->do_Left;
  1088.     dy+=h;
  1089.     col=0;
  1090.    } else
  1091.     /* No */
  1092.     dx+=w;
  1093.  
  1094.    /* Get pointer to next dock tool */
  1095.    dt=dt->dt_Next;
  1096.   }
  1097.  
  1098.  /* Dock tool not found */
  1099.  return(NULL);
  1100. }
  1101.  
  1102. /* Activate one dock entry */
  1103. static BOOL ActivateDockEntry(struct TMObjectDock *tmobj, struct DockTool *dt,
  1104.                               struct AppMessage *msg, ULONG anim)
  1105. {
  1106.  /* Activate Sound object */
  1107.  if (dt->dt_SoundLink) CallActivateTMObject(dt->dt_SoundLink,NULL);
  1108.  
  1109.  /* Activate Image object */
  1110.  if (!(tmobj->do_Flags & DO_Text) && dt->dt_ImageLink && anim)
  1111.     CallActivateTMObject((struct TMLink *) dt->dt_ImageLink,(void *) anim);
  1112.  
  1113.  /* Set defered close flag */
  1114.  tmobj->do_DeferClose=TRUE;
  1115.  
  1116.  /* Activate Exec object */
  1117.  if (dt->dt_ExecLink) CallActivateTMObject(dt->dt_ExecLink,msg);
  1118.  
  1119.  /* PopUp dock or defered close? Yes, close window */
  1120.  if ((tmobj->do_Flags & DO_PopUp) || !tmobj->do_DeferClose)
  1121.   return(TRUE);
  1122.  else {
  1123.   /* Reset defered close flag */
  1124.   tmobj->do_DeferClose=FALSE;
  1125.   return(FALSE);
  1126.  }
  1127. }
  1128.  
  1129. /* Activate a Dock object */
  1130. void ActivateTMObjectDock(struct TMLink *tml, struct AppMessage *msg)
  1131. {
  1132.  struct TMObjectDock *tmobj=(struct TMObjectDock *) tml->tml_Linked;
  1133.  
  1134.  DEBUG_PRINTF("Activate/Dock (0x%08lx)\n",msg);
  1135.  
  1136.  /* Got arguments? */
  1137.  if (msg) {
  1138.   /* Yes. Icons were dropped on the dock */
  1139.   struct DockTool *dt;
  1140.  
  1141.   /* Find Tool */
  1142.   if (dt=FindDockTool(tmobj,msg->am_MouseX,msg->am_MouseY)) {
  1143.    /* Activate dock entry */
  1144.    if (ActivateDockEntry(tmobj,dt,msg,IOC_FULLANIM))
  1145.     CloseDockWindow(tmobj);
  1146.  
  1147.    /* Clear pointer */
  1148.    tmobj->do_Selected=NULL;
  1149.   }
  1150.  }
  1151.  /* No. User pressed HotKey. Window open? */
  1152.  else if (tmobj->do_Window)
  1153.   /* Defered close? */
  1154.   if (tmobj->do_DeferClose)
  1155.    /* Yes, clear flag */
  1156.    tmobj->do_DeferClose=FALSE;
  1157.   else
  1158.    /* No, close window and free its resources */
  1159.    CloseDockWindow(tmobj);
  1160.  else {
  1161.   /* Window not open. Open it. */
  1162.   OpenDockWindow(tmobj);
  1163.  
  1164.   /* If DO_FrontMost is not set, move screen to front */
  1165.   if (!(tmobj->do_Flags & DO_FrontMost) && tmobj->do_Window)
  1166.    ScreenToFront(tmobj->do_Window->WScreen);
  1167.  }
  1168. }
  1169.  
  1170. /* Handle IDCMP events */
  1171. void HandleIDCMPEvents(void)
  1172. {
  1173.  struct IntuiMessage *msg;
  1174.  
  1175.  /* Scan IDCMP message port */
  1176.  while (msg=GT_GetIMsg(IDCMPPort)) {
  1177.   struct TMObjectDock *tmobj=(struct TMObjectDock *) msg->IDCMPWindow->UserData;
  1178.   BOOL closewindow=FALSE;
  1179.  
  1180.   DEBUG_PRINTF("IDCMP Class: 0x%08lx\n",msg->Class);
  1181.  
  1182.   switch (msg->Class) {
  1183.    case IDCMP_CLOSEWINDOW:    /* Set close flag */
  1184.                               closewindow=TRUE;
  1185.                               break;
  1186.    case IDCMP_REFRESHWINDOW:  {
  1187.                                struct Window *w=tmobj->do_Window;
  1188.  
  1189.                                GT_BeginRefresh(w);
  1190.                                GT_EndRefresh(w,TRUE);
  1191.                               }
  1192.                               break;
  1193.    case IDCMP_MOUSEBUTTONS:   /* Only docks with images need button events */
  1194.                               if (!(tmobj->do_Flags & DO_Text))
  1195.                                switch (msg->Code) {
  1196.                                 case SELECTDOWN: /* Select button pressed */
  1197.                                  {
  1198.                                   struct DockTool *dt;
  1199.  
  1200.                                   if (dt=FindDockTool(tmobj,msg->MouseX,
  1201.                                                             msg->MouseY)) {
  1202.                                    struct TMLinkImage *tmli=dt->dt_ImageLink;
  1203.  
  1204.                                    DEBUG_PRINTF("Dock selected: 0x%08lx\n",dt);
  1205.  
  1206.                                    /* Got a dock tool with image object? */
  1207.                                    if (tmli)
  1208.                                     /* Image object with active anim? */
  1209.                                     if (tmli->tmli_Link.tml_Active)
  1210.                                      /* Yes, clear pointer */
  1211.                                      tmobj->do_Selected=NULL;
  1212.                                     else
  1213.                                      /* No, select it */
  1214.                                      CallActivateTMObject((struct TMLink *)
  1215.                                                           tmli,
  1216.                                                           (void *) IOC_ACTIVE);
  1217.                                   }
  1218.                                  }
  1219.                                  break;
  1220.                                 case SELECTUP:   /* Select button released */
  1221.                                  {
  1222.                                   struct DockTool *dt=tmobj->do_Selected;
  1223.  
  1224.                                   /* Got a selected dock tool? */
  1225.                                   if (dt) {
  1226.                                    struct TMLinkImage *tmli=dt->dt_ImageLink;
  1227.  
  1228.                                    /* Dock tool with image object? */
  1229.                                    if (tmli) {
  1230.                                     UWORD x=msg->MouseX;
  1231.                                     UWORD y=msg->MouseY;
  1232.                                     UWORD dx=tmobj->do_SelectX;
  1233.                                     UWORD dy=tmobj->do_SelectY;
  1234.  
  1235.                                     /* Mouse still on dock tool and no */
  1236.                                     /* double click?                   */
  1237.                                     if ((x>=dx) && (y>=dy) &&
  1238.                                         (x<dx+tmobj->do_XSize) &&
  1239.                                         (y<dy+tmobj->do_YSize) &&
  1240.                                         !DoubleClick(tmobj->do_Seconds,
  1241.                                                      tmobj->do_Micros,
  1242.                                                      msg->Seconds,
  1243.                                                      msg->Micros)) {
  1244.                                      /* Yes. Activate dock entry */
  1245.                                      closewindow=ActivateDockEntry(tmobj,dt,
  1246.                                                             NULL,IOC_CONTANIM);
  1247.  
  1248.                                      /* Save time stamp */
  1249.                                      tmobj->do_Seconds=msg->Seconds;
  1250.                                      tmobj->do_Micros=msg->Micros;
  1251.                                     }
  1252.                                     else
  1253.                                      /* No, de-select image */
  1254.                                      CallActivateTMObject((struct TMLink *)
  1255.                                                           dt->dt_ImageLink,
  1256.                                                           (void *) IOC_DEACTIVE
  1257.                                                          );
  1258.                                    }
  1259.  
  1260.                                    /* Clear pointer */
  1261.                                    tmobj->do_Selected=NULL;
  1262.                                   }
  1263.                                  }
  1264.                                  break;
  1265.                                }
  1266.                               break;
  1267.    case IDCMP_GADGETUP:       /* Prevent double clicks */
  1268.                               if (!DoubleClick(tmobj->do_Seconds,
  1269.                                                tmobj->do_Micros,
  1270.                                                msg->Seconds,msg->Micros)) {
  1271.                                struct DockTool *dt=(struct DockTool *)
  1272.                                 ((struct Gadget *) msg->IAddress)->UserData;
  1273.  
  1274.                                /* Activate dock entry */
  1275.                                closewindow=ActivateDockEntry(tmobj,dt,NULL,0);
  1276.  
  1277.                                /* Save time stamp */
  1278.                                tmobj->do_Seconds=msg->Seconds;
  1279.                                tmobj->do_Micros=msg->Micros;
  1280.                               }
  1281.                               break;
  1282.    case IDCMP_MENUPICK:       {
  1283.                                USHORT menunum=msg->Code;
  1284.  
  1285.                                /* Scan all menu events */
  1286.                                while (menunum!=MENUNULL) {
  1287.                                 struct MenuItem *menuitem=
  1288.                                  ItemAddress(tmobj->do_Menu,menunum);
  1289.  
  1290.                                 /* Which menu selected? */
  1291.                                 switch(GTMENUITEM_USERDATA(menuitem)) {
  1292.                                  case MENU_CLOSE: closewindow=TRUE;
  1293.                                                   break;
  1294.                                  case MENU_QUIT:  Closing=TRUE;
  1295.                                                   break;
  1296.                                 }
  1297.  
  1298.                                 /* Get next menu event */
  1299.                                 menunum=menuitem->NextSelect;
  1300.                                }
  1301.                               }
  1302.                               break;
  1303.    case IDCMP_ACTIVEWINDOW:   if (!tmobj->do_Title) {
  1304.                                /* Borderless window */
  1305.                                struct RastPort *rp=tmobj->do_Window->RPort;
  1306.                                struct Gadget *g=&tmobj->do_DragGadget;
  1307.  
  1308.                                SetDrMd(rp,JAM1);
  1309.                                SetAPen(rp,tmobj->do_FillPen);
  1310.                                RectFill(rp,1,1,g->Width-2,g->Height-2);
  1311.                               }
  1312.                               break;
  1313.    case IDCMP_INACTIVEWINDOW: {
  1314.                                struct DockTool *dt=tmobj->do_Selected;
  1315.  
  1316.                                if (!tmobj->do_Title) {
  1317.                                 /* Borderless window */
  1318.                                 struct RastPort *rp=tmobj->do_Window->RPort;
  1319.                                 struct Gadget *g=&tmobj->do_DragGadget;
  1320.  
  1321.                                 SetDrMd(rp,JAM1);
  1322.                                 SetAPen(rp,tmobj->do_BackPen);
  1323.                                 RectFill(rp,1,1,g->Width-2,g->Height-2);
  1324.                                }
  1325.  
  1326.                                /* Missed a selectup??? */
  1327.                                if (dt) {
  1328.                                 struct TMLinkImage *tmli=dt->dt_ImageLink;
  1329.  
  1330.                                 /* Got non-ANIM image object? */
  1331.                                 if (tmli && !tmli->tmli_Link.tml_Active)
  1332.                                  CallActivateTMObject((struct TMLink *) tmli,
  1333.                                                       (void *) IOC_DEACTIVE);
  1334.  
  1335.                                 tmobj->do_Selected=NULL;
  1336.                                }
  1337.                               }
  1338.                               break;
  1339.   }
  1340.  
  1341.   /* Reply message */
  1342.   GT_ReplyIMsg(msg);
  1343.  
  1344.   /* Close window? */
  1345.   if (closewindow) CloseDockWindow(tmobj);
  1346.  }
  1347. }
  1348.